﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using Game.Lib;
using System.Threading;

namespace Game
{
    public partial class AccountServer : Form
    {
        private bool isExit = false;
        System.Collections.ArrayList clientList = new System.Collections.ArrayList();
        TcpListener listener = null;
        int account_gateway, port;
        Database db = null;
        string host, uid, pwd, name;
        Result rs = null;

        private delegate void SetListBoxLogsCallback(string str);
        private SetListBoxLogsCallback setListBoxLogsCallback;

        public AccountServer()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
            setListBoxLogsCallback = new SetListBoxLogsCallback(SetListBoxLogs);
        }

        private void AccountServer_FormClosing(object sender, FormClosingEventArgs e)
        {
            DialogResult result = MessageBox.Show("确定停止账号网关?", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (result == DialogResult.Yes)
            {
                e.Cancel = false;
                listener.Stop();
                isExit = true;
                GameServer Gs = (GameServer)this.Owner;
                Gs.buttonStopAccountServer.Enabled = false;
                Gs.buttonStartAccountServer.Enabled = true;
                Gs.listBoxLogs.Items.Add(String.Format("[{0}]账号网关停止.", DateTime.Now.ToShortTimeString()));
                Gs.As = null;
            }
            else
            {
                e.Cancel = true;
            }
        }

        private void AccountServer_Load(object sender, EventArgs e)
        {
            //加载配置
            LoadSetting();
            //开启TCP监听线程
            ThreadStart ts = new ThreadStart(Listen);
            Thread listen = new Thread(ts);
            listen.Start();
            //连接数据库
            ConnectDatabase();
        }

        /// <summary>
        /// 加载配置
        /// </summary>
        private void LoadSetting()
        {
            IniFiles iniFiles = new IniFiles(@"setting.ini");
            account_gateway = iniFiles.ReadInteger("gateway", "account", 10001);
            host = iniFiles.ReadString("database", "host", "localhost");
            port = iniFiles.ReadInteger("database", "port", 3306);
            uid = iniFiles.ReadString("database", "user", "root");
            pwd = iniFiles.ReadString("database", "password", "root");
            name = iniFiles.ReadString("database", "name", "game");
        }

        /// <summary>
        /// 连接数据库
        /// </summary>
        private void ConnectDatabase()
        {
            try
            {
                db = new Database(host, port, uid, pwd, name);
            }
            catch (Exception err)
            {
                listBoxLogs.Invoke(setListBoxLogsCallback, "数据库连接失败!"+err.Message);
            }
        }

        /// <summary>
        /// 开始监听客户端连接
        /// </summary>
        private void Listen()
        {
            string hostname = Dns.GetHostName();
            IPHostEntry IpEntry = Dns.GetHostEntry(hostname);
            for (int i = 0; i < IpEntry.AddressList.Length; i++)
            {
                if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
                {
                    listener = new TcpListener(IpEntry.AddressList[i], account_gateway);
                    listener.Start();
                    break;
                }
            }

            listBoxLogs.Invoke(setListBoxLogsCallback, "账号网关启动成功,等待连接...");
            while (isExit == false)
            {
                try
                {
                    TcpClient client = listener.AcceptTcpClient();
                    listBoxLogs.Invoke(setListBoxLogsCallback, "已接受客户端连接" + client.Client.RemoteEndPoint);
                    ReadWriteObject obj = new ReadWriteObject(client);
                    SendString(obj, "成功连接至服务端");
                    //读取客户端消息
                    string msg = ReadString(obj);
                    //去除首尾空格，并利用空格分割参数
                    string[] s = msg.Trim().Split(new char[] { ' ' });
                    //命令类型
                    string cmd = s[0];
                    //命令数据
                    string data = s[1];
                    switch (cmd)
                    {
                        case "REGISTER":
                            Result rs = Register(data);
                            SendString(obj, rs.msg);
                            break;
                        default:
                            SendString(obj, "内部错误!");
                            break;
                    }
                }
                catch (Exception err)
                {
                    Log.Write(String.Format("[{0}]{1}",DateTime.Now.ToLocalTime(),err.Message));
                }
            }
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="readWriteObject">TcpClient读写对象</param>
        /// <param name="str">消息</param>
        private void SendString(ReadWriteObject readWriteObject, string str)
        {
            try
            {
                readWriteObject.writeBytes = System.Text.Encoding.UTF8.GetBytes(str + "\r\n");
                readWriteObject.netStream.Write(readWriteObject.writeBytes, 0, readWriteObject.writeBytes.Length);
                readWriteObject.netStream.Flush();
            }
            catch (Exception err)
            {
                listBoxLogs.Invoke(setListBoxLogsCallback, err.Message);
            }
        }

        /// <summary>
        /// 读取消息
        /// </summary>
        /// <param name="readWriteObject">读写对象</param>
        /// <returns>消息</returns>
        private string ReadString(ReadWriteObject readWriteObject)
        {
            if (isExit == false)
            {
                try
                {
                    readWriteObject.InitReadArray();
                    string str = System.Text.Encoding.UTF8.GetString(readWriteObject.readBytes, 0, readWriteObject.readBytes.Length);
                    return str;
                }
                catch (Exception err)
                {
                    listBoxLogs.Invoke(setListBoxLogsCallback, err.Message);
                    return "";
                }
            }
            else
            {
                return "";
            }
        }

        /// <summary>
        /// 用户注册
        /// </summary>
        /// <param name="info">注册信息</param>
        /// <returns>注册结果</returns>
        private Result Register(string info)
        {
            //分割字符串
            string[] s = info.Split(new char[] { '|' });
            string username = s[0];
            string password = s[1];
            string nickname = s[2];
            string email = s[3];

            //构造SQL
            string sql = String.Format("INSERT INTO `account` (`username`,`password`,`nickname`,`email`,`register_at`) VALUES ('{0}',MD5('{1}'),'{2}','{3}',NOW())", username, password, email);
            //检测重复用户
            string check = String.Format("SELECT `account_id` from `account` where `username` = '{0}' AND `password` = MD5('{1}')", username, password);
            try
            {
                object obj = db.ExecuteScalar(check);
                if (obj != null)
                {
                    rs.result = false;
                    rs.msg = "账号已存在!";
                    return rs;
                }
                else
                {
                    db.ExecuteNonQuery(sql);
                    rs.result = true;
                    rs.msg = "注册成功!";
                    return rs;
                }
            }
            catch (Exception err)
            {
                rs.result = false;
                rs.msg = "注册失败!\n提示消息:" + err.Message;
                return rs;
            }
        }

        /// <summary>
        /// 写入系统信息
        /// </summary>
        /// <param name="str">消息</param>
        private void SetListBoxLogs(string str)
        {
            listBoxLogs.Items.Add(String.Format("[{0}]{1}", DateTime.Now.ToShortTimeString(), str));
            listBoxLogs.SelectedIndex = listBoxLogs.Items.Count - 1;
            listBoxLogs.ClearSelected();
        }
    }
}
